package com.example.javacore.listobject;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.example.vo.StudentVO;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

public class ListUtil {

    public static void existValue() {
        List<StudentVO> list = StudentVO.init();
        System.out.println("是否存在id是1:" + list.stream().anyMatch(m -> "1".equals(m.getId())));
    }

    public static void removeRepeat() {
        List<String> stringList = Arrays.asList("1", "1", "2");
        List<String> newList = stringList.stream().distinct().collect(Collectors.toList());
        System.out.println("基本数据类型去重:" + newList);

        List<StudentVO> list = StudentVO.initRepeatData();
        List<StudentVO> collect = list.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(StudentVO::getId))), ArrayList::new));
        System.out.println("对象：单个字段ID去重,保留不确定的记录:" + collect);

        collect = list.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.getId() + ";" + s.getAge()))), ArrayList::new));
        System.out.println("对象：多个字段去重,ID和age都相等只保留一条记录:" + collect);

        Map<String, StudentVO> map = new TreeMap<>();
        for (StudentVO t : list) {
            if (map.containsKey(t.getId())) {
                if (t.getScore() > map.get(t.getId()).getScore()) {
                    map.put(t.getId(), t);
                }
            } else {
                map.put(t.getId(), t);
            }
        }
        list = new ArrayList<>(map.values());
        System.out.println("对象：去除ID重复的记录,并保留score最高的记录:" + list);
    }

    public static void filterByField() {
        List<StudentVO> list = StudentVO.init();
        String id = "1";
        List<StudentVO> filter = list.stream().filter(item -> item.getId().equals(id) || "2".equals(item.getId())).collect(Collectors.toList());

        System.out.println("获得过滤结果,true留下:" + filter);
        list.stream().filter(item ->
                item.getId().equals(id)
        ).forEach(n -> {
            System.out.println("循环过滤结果:");
            System.out.println(n);
        });
    }

    public static void allMatch() {
        List<StudentVO> list = StudentVO.init();
        boolean allMatch = list.stream().allMatch(item -> item.getAge() < 90);
        if (allMatch) {
            System.out.println("所有年龄都<90");
        } else {
            System.out.println("不是所有年龄都<90");
        }
    }

    public static void aggregate() {
        List<StudentVO> list = StudentVO.init();
        Optional<StudentVO> max = list.stream().max(Comparator.comparingInt(StudentVO::getAge));
        Optional<StudentVO> min = list.stream().min(Comparator.comparingInt(StudentVO::getAge));
        System.out.println("最小日期:" + list.stream().min(Comparator.comparing(StudentVO::getBirthDay)).orElse(new StudentVO()).getBirthDay());
        System.out.println("最大日期:" + list.stream().max(Comparator.comparing(StudentVO::getBirthDay)).orElse(new StudentVO()).getBirthDay());
        System.out.println("年龄最大的:" + max.orElse(new StudentVO()));
        System.out.println("年龄最小的:" + min.orElse(new StudentVO()));
        System.out.println("年龄大于20的个数:" + list.stream().filter(n -> n.getAge() > 20).count());
    }

    public static void noneMatch() {
        List<StudentVO> list = StudentVO.init();
        boolean none = list.stream().noneMatch(m -> m.getAge() >= 100);
        if (none) {
            System.out.println("不存在大于100的记录");
        } else {
            System.out.println("存在大于100的记录");
        }
    }

    public static void toArray() {
        List<StudentVO> list = StudentVO.init();
        String[] ids = list.stream().map(StudentVO::getId).toArray(String[]::new);
        System.out.println("转换为String数组:" + JSON.toJSONString(ids));
        String[] dates = list.stream().map(obj -> DateUtil.format(obj.getBirthDay(), "yyyy-MM-dd")).toArray(String[]::new);
        System.out.println("日期转换为String数组:" + JSON.toJSONString(dates));
        List<String> idListStr = list.stream().map(StudentVO::getId).collect(Collectors.toList());
        System.out.println("转换为List数组:" + JSON.toJSONString(idListStr));
    }

    public static void getFieldAndRemoveDuplicate() {
        List<StudentVO> list1 = StudentVO.init();
        List<StudentVO> list2 = StudentVO.init();
        List<StudentVO> list = new ArrayList<>();
        list.addAll(list1);
        list.addAll(list2);

        System.out.println("去重前ID:" + JSON.toJSONString(list.stream().map(StudentVO::getId).toArray(String[]::new)));
        String[] ids = list.stream().map(StudentVO::getId).distinct().toArray(String[]::new);
        System.out.println("ID去重后:" + JSON.toJSONString(ids));
        List<String> idListStr = list.stream().map(StudentVO::getId).distinct().collect(Collectors.toList());
        System.out.println("ID去重后:" + JSON.toJSONString(idListStr));
    }

    public static void findFirstSameRecord() {
        List<StudentVO> list = StudentVO.init();
        Optional<StudentVO> optional = list.stream().filter(item -> "20".equals(item.getId())).findFirst();
        if (optional.isPresent()) {
            System.out.println("找到相同的记录:" + JSON.toJSON(optional.get()));
        } else {
            System.out.println("没有找到相同的记录");
        }
        System.out.println("查找结果:" + JSON.toJSON(optional.orElse(null)));
    }

    /**
     * 返回集合中找到的所有记录
     */
    public static void findAllSameRecord() {
        List<StudentVO> list = StudentVO.init();
        List<StudentVO> result = list.stream().filter(item -> item.getAge() > 21).collect(Collectors.toList());
        System.out.println(result);
    }

    /**
     * 返回集合中找到的所有记录并将某元素转换成集合
     */
    public static void findAndConvert() {
        List<StudentVO> list = StudentVO.init();
        List<String> result = list.stream().filter(item -> item.getAge() > 21).map(StudentVO::getName).collect(Collectors.toList());
        System.out.println(result);
    }

    /**
     * 查找两个集合存在相同的元素的任意一条记录
     */
    public static void equalsRecord() {
        List<StudentVO> list1 = StudentVO.init();
        List<StudentVO> list2 = StudentVO.init2();
        Optional<StudentVO> optional = list1.stream().filter(i1 -> list2.stream().anyMatch(i2 -> (i1.getName().equals(i2.getName())))).findAny();
        System.out.println(optional.orElse(null));
    }

    /**
     * 按照集合某字段排序
     */
    public static void sortByOneFiled() {
        List<StudentVO> list = StudentVO.init();

        list.sort(Comparator.comparingInt(StudentVO::getAge));
        System.out.println("年龄升序:" + JSON.toJSONString(list));

        list.sort(Comparator.comparingInt(StudentVO::getAge).reversed());
        System.out.println("年龄降序:" + JSON.toJSONString(list));

        list.sort(Comparator.comparing(StudentVO::getBirthDay));
        System.out.println("日期升序:" + JSON.toJSONString(list));

        list.sort(Comparator.comparing(StudentVO::getBirthDay).reversed());
        System.out.println("日期降序:" + JSON.toJSONString(list));
    }

    /**
     * 按照集合某字段排序
     */
    public static void sortByManyFiled() {
        List<StudentVO> list = JSON.parseArray("[{\"id\":\"3\",\"age\":10},{\"id\":\"3\",\"age\":20},{\"id\":\"5\",\"age\":30},{\"id\":\"5\",\"age\":20},{\"id\":\"1\",\"age\":10},{\"id\":\"1\",\"age\":20}]", StudentVO.class);
        System.out.println("排序前:" + JSON.toJSONString(list));

        // ID升序,年龄降序
        list.sort(Comparator.comparing(StudentVO::getId).thenComparing(StudentVO::getAge, Comparator.reverseOrder()));
        System.out.println("ID升序,年龄降序:" + JSON.toJSONString(list));
    }

    /**
     * 判断两个集合是否存在相同元素
     */
    public static void existEquals() {
        List<StudentVO> list1 = StudentVO.init();
        List<StudentVO> list2 = StudentVO.init2();
        System.out.println(list1.stream().anyMatch(i1 -> list2.stream().anyMatch(i2 -> (i1.getName().equals(i2.getName())))));
    }

    /**
     * 集合A中某属性值和集合B中属性值相等的记录
     */
    public static void listEqualsRecord() {
        List<StudentVO> list1 = StudentVO.init();
        List<StudentVO> list2 = StudentVO.init2();
        List<StudentVO> eq = list1.stream().filter(a -> list2.stream().anyMatch(b -> (a.getId().equals(b.getId())))).collect(Collectors.toList());
        System.out.println(eq);
    }

    /**
     * 集合A中属性不在集合B中记录
     */
    public static void listOneNotInListTwoRecord() {
        List<StudentVO> list1 = JSON.parseArray("[{\"id\":\"1\",\"age\":10,\"sex\":\"男\"}," +
                "{\"id\":\"2\",\"age\":20,\"sex\":\"女\"}," +
                "{\"id\":\"3\",\"age\":22,\"sex\":\"女\"}]", StudentVO.class);
        List<StudentVO> list2 = JSON.parseArray("[{\"id\":\"1\",\"age\":10,\"sex\":\"男\"}," +
                "{\"id\":\"2\",\"age\":20,\"sex\":\"女\"}," +
                "{\"id\":\"3\",\"age\":22,\"sex\":\"女\"}]", StudentVO.class);
        List<StudentVO> eq = list1.stream().filter(a -> list2.stream().noneMatch(b -> (a.getId().equals(b.getId())))).collect(Collectors.toList());
        System.out.println(eq);
    }

    public static void groupBySex() {
        List<StudentVO> list = JSON.parseArray("[{\"id\":\"3\",\"age\":10,\"sex\":\"男\"}," +
                "{\"id\":\"3\",\"age\":20,\"sex\":\"女\"}," +
                "{\"id\":\"5\",\"age\":30,\"sex\":\"男\"}," +
                "{\"id\":\"5\",\"age\":19,\"sex\":\"女\"}," +
                "{\"id\":\"1\",\"age\":10,\"sex\":\"男\"}," +
                "{\"id\":\"1\",\"age\":22,\"sex\":\"女\"}]", StudentVO.class);
        Map<String, List<StudentVO>> map = list.stream().collect(groupingBy(StudentVO::getSex));
        System.out.println("按男女分组:" + map);
        List<String> group = new ArrayList<>();
        List<List<StudentVO>> value = new ArrayList<>();
        map.forEach((k, v) -> {
            group.add(k);
            value.add(v);
        });
        System.out.println("分组:" + group);
        System.out.println("分组值:" + value);
    }

    public static void sumByFilter() {
        String init = "[" +
                "{\"age\":21,\"birthDay\":'2020-01-01 12:34:23'}" +
                "{\"age\":25,\"birthDay\":'2021-01-05 12:34:23'}" +
                "{\"age\":20,\"birthDay\":'2022-12-12 13:34:23'}" +
                "]";
        List<StudentVO> list = JSON.parseArray(init, StudentVO.class);
        int sum = list.stream().filter(
                        obj -> obj.getBirthDay().compareTo(DateUtil.parse("2022-12-12 13:34:23", "yyyy-MM-dd HH:mm:ss")) <= 0
                                && obj.getBirthDay().compareTo(DateUtil.parse("2021-01-05 12:34:23", "yyyy-MM-dd HH:mm:ss")) >= 0)
                .mapToInt(StudentVO::getAge).sum();
        System.out.println("日期范围内的和:" + sum);
    }

}
